package cn.turboinfo.dongying.api.domain.admin.usecase.user;

import cn.turboinfo.dongying.api.domain.common.service.role.RoleService;
import cn.turboinfo.dongying.api.domain.common.service.user.SysUserRoleService;
import cn.turboinfo.dongying.api.domain.common.service.user.SysUserService;
import cn.turboinfo.dongying.api.domain.common.service.user.UserTypeRelService;
import cn.turboinfo.dongying.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.dongying.api.entity.admin.pojo.role.Role;
import cn.turboinfo.dongying.api.entity.common.enumeration.common.EntityObjectType;
import cn.turboinfo.dongying.api.entity.common.enumeration.user.UserType;
import cn.turboinfo.dongying.api.entity.common.pojo.user.SysUser;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Sets;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 后台分配角色用例
 *
 * @author sunshow
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class AdminReassignUserRoleUseCase extends AbstractUseCase<AdminReassignUserRoleUseCase.InputData, AdminReassignUserRoleUseCase.OutputData> {

    private final RoleService roleService;

    private final SysUserService sysUserService;

    private final SysUserRoleService sysUserRoleService;

    private final UserTypeRelService userTypeRelService;

    @Override
    protected OutputData doAction(InputData inputData) {
        Long sysUserId = inputData.getSysUserId();
        Long[] checkedRoleIds = MoreObjects.firstNonNull(inputData.getCheckedRoleIds(), new Long[0]);

        // 验证用户是否存在
        SysUser sysUser = sysUserService.getByIdEnsure(sysUserId);

        // 限制保留角色分配问题
        // 涉及用户类型的保留角色不允许自由分配
        Map<Long, Role> userTypeRoleIdMap = roleService.findByCodeCollection(UserType.listRoleCode()
                        // 过滤掉平台运营角色
                        .stream().filter(it -> !Objects.equals(it, UserType.Platform.getRoleCode())
                                && !Objects.equals(it, UserType.Community.getRoleCode()) && !Objects.equals(it, UserType.Division.getRoleCode()))
                        .collect(Collectors.toList())
                )
                .stream()
                .collect(Collectors.toMap(Role::getId, Function.identity()));

        // 不允许分配用户类型角色
//        Optional<Long> shouldNotAssignRoleIdOptional = Arrays.stream(checkedRoleIds).filter(userTypeRoleIdMap::containsKey).findFirst();
//        if (shouldNotAssignRoleIdOptional.isPresent()) {
//            throw new RuntimeException("不允许分配的角色: " + userTypeRoleIdMap.get(shouldNotAssignRoleIdOptional.get()).getName());
//        }
        Set<Long> checkedRoleIdSet = Sets.newHashSet(checkedRoleIds);

        final val setRoleCode = roleService.findByIdCollection(checkedRoleIdSet).stream().map(Role::getCode).collect(Collectors.toSet());
        boolean hasCommunityRole = setRoleCode.contains(UserType.Community.getRoleCode());
        boolean hasShopRole = setRoleCode.contains(UserType.Shop.getRoleCode());
        if (hasCommunityRole && hasShopRole) {
            throw new RuntimeException("社区角色不能商户角色同时共用");
        }
        if (hasCommunityRole && inputData.getCommunityId() == null) {
            throw new RuntimeException("请选择社区");
        }
        //保存社区关联
        userTypeRelService.deleteByIdCollection(userTypeRelService.findByUserIdAndUserTypeAndObjectType(sysUser.getId(), UserType.Community, EntityObjectType.COMMUNITY)
                .stream()
                .map(it -> it.getId())
                .collect(Collectors.toList()));
        Long communityId = inputData.getCommunityId();
        if (communityId != null && hasCommunityRole) {
            userTypeRelService.createCommunityRel(sysUser.getId(), communityId);
        }

        //保存地区关联
        userTypeRelService.deleteByIdCollection(userTypeRelService.findByUserIdAndUserTypeAndObjectType(sysUser.getId(), UserType.Default, EntityObjectType.DIVISION)
                .stream()
                .map(it -> it.getId())
                .collect(Collectors.toList()));
        if (inputData.getCheckedDivisionIds() != null && inputData.getCheckedDivisionIds().length > 0) {
            userTypeRelService.createDivisionRel(sysUser.getId(), Arrays.asList(inputData.getCheckedDivisionIds()));
        }

        // 实际分配角色
        sysUserRoleService.reassign(sysUser.getId(), checkedRoleIdSet);
        return OutputData.builder()
                .build();
    }

    @Getter
    @Setter
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        @NotNull(message = "用户不能为空")
        private Long sysUserId;

        private Long[] checkedRoleIds;

        private Long[] checkedDivisionIds;

        private Long communityId;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

    }
}
